package com.yuexunit.finance.common.util;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

/**
 * List排序工具 </p>
 * 下面的例子假定被排序的对象class为TestUser,按score降序,再按name升序,排序的list为testUsers </p>
 * 调用方法如下：   </p>
 * ListSorter<TestUser> sorter = new ListSorter<TestUser>(TestUser.class);</p>
 * sorter.orderByDesc("score").orderByAsc("name");</p>
 * sorter.sort(testUsers);</p>
 *
 */
public class ListSorter<T> {

    private List<OrderField> orderFields = new ArrayList<OrderField>();

    private final Class orderClazz;

    /**
     * 构造方法
     *
     * @param orderClazz 排序类
     */
    public ListSorter(final Class<T> orderClazz) {
        this.orderClazz = orderClazz;
    }

    /**
     * @param orderClazz 排序类
     * @param fieldName  排序字段名
     * @param isDesc     是否降序
     */
    public ListSorter(final Class<T> orderClazz, String fieldName, boolean isDesc) {
        this.orderClazz = orderClazz;
        OrderField orderField = new OrderField(fieldName, isDesc);
        orderFields.add(orderField);
    }


    /**
     * 增加一个降序字段
     *
     * @param fieldName 排序字段名
     */
    public ListSorter<T> orderByDesc(String fieldName) {
        OrderField orderField = new OrderField(fieldName, true);
        orderFields.add(orderField);
        return this;
    }

    /**
     * 增加一个升序字段
     *
     * @param fieldName 排序字段名
     */
    public ListSorter<T> orderByAsc(String fieldName) {
        OrderField orderField = new OrderField(fieldName, false);
        orderFields.add(orderField);
        return this;
    }

    /**
     * 添加排序字段
     *
     * @param fieldName 排序字段名
     * @param isDesc    是否降序
     * @return .
     */
    public ListSorter<T> orderBy(String fieldName, boolean isDesc) {
        OrderField orderField = new OrderField(fieldName, isDesc);
        orderFields.add(orderField);
        return this;
    }

    /**
     * 添加排序字段
     *
     * @param orderField .
     * @return .
     */
    public ListSorter<T> addOrderField(OrderField orderField) {
        orderFields.add(orderField);
        return this;
    }

    /**
     * 添加排序字段
     *
     * @param orderFieldArray .
     */
    public void addOrderField(OrderField... orderFieldArray) {
        Collections.addAll(orderFields, orderFieldArray);
    }

    /**
     * 添加排序字段
     *
     * @param orderFieldList .
     */
    public void addOrderField(List<OrderField> orderFieldList) {
        orderFields.addAll(orderFieldList);
    }
    
    @SuppressWarnings("unchecked")
    public void sort(List<T> list, final String method, final String sort){
        Collections.sort(list, new Comparator() {
          public int compare(Object a, Object b) {
            int ret = 0;
            try{
              Method m1 = ((T)a).getClass().getMethod(method, null);
              Method m2 = ((T)b).getClass().getMethod(method, null);
              if(sort != null && "desc".equals(sort))//倒序
              {
            	  if(m1.invoke(b)==null)return -1;
            	  if(m1.invoke(a)==null)return 1;
            	  ret = m2.invoke(((T)b), null).toString().compareTo(m1.invoke(((T)a), null).toString());
              }else{//正序
            	  if(m1.invoke(a)==null)return -1;
            	  if(m1.invoke(b)==null)return 1;
            	  ret = m1.invoke(((T)a), null).toString().compareTo(m2.invoke(((T)b), null).toString());
              }
            }catch(NoSuchMethodException ne){
              System.out.println(ne);
            }catch(IllegalAccessException ie){
              System.out.println(ie);
            }catch(InvocationTargetException it){
              System.out.println(it);
            }
            return ret;
          }
         });
      }

    /**
     * 排序方法
     *
     * @param list 被排序list
     * @return 排序后的list
     */
    public List<T> sort(List<T> list) {
        Comparator<T> comparator = getComparator();
        if (comparator != null) {
            Collections.sort(list, comparator);
        }
        return list;
    }

    /**
     * 排序方法，无返回
     * 
     * @param list 被排序的list，完成后其元素顺序已排
     */
    public void sortWithoutReply(List<T> list) {
//        Comparator<T> comparator = getComparator();
//        if (comparator != null) {
//            Collections.sort(list, comparator);
//        }
    	sort(list);
    }

    /**
     * 取得Comparator
     * 按照Comparator class name查找OrderUtils中的缓存，如果存在则取出，不存在生成一个，异常时返回null
     *
     * @return 异常时返回null
     */
    private Comparator<T> getComparator() {

        OrderField[] orderFieldArray = orderFields.toArray(new OrderField[orderFields.size()]);
        String comparatorClassName = OrderUtils.getNewClassName(orderClazz, orderFieldArray);
        Comparator<T> comparator = OrderUtils.getComparator(comparatorClassName);
        if (comparator == null) {
            try {
            	 //不进行并发控制，当出现重复加载时在调用一次
                    comparator = OrderUtils.getComparator(comparatorClassName);
                    if (null == comparator) {
                        String comparatorSourceCode = OrderUtils.createCopmare(
                                orderClazz, orderFieldArray);
                        comparator = (Comparator<T>) OrderUtils.doCompile(
                                comparatorClassName, comparatorSourceCode)
                                .newInstance();
                        OrderUtils.addComparator(comparatorClassName,
                                comparator);
                    }

            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (Throwable e) {
                e.printStackTrace();
            }
        }
        if (null == comparator) {
        	comparator = OrderUtils.getComparator(comparatorClassName);
        }

        return comparator;
    }
}